/* ******************************* *
 *       -=# Array Life #=-        *
 *             =====               *
 *         By: TarpeyD12           *
 * =============================== *
 *        Version: 0.3.5.9         *
 * ******************************* *
 *           Main file.            *
 *           al_main.c             *
 * ******************************* */

#include "array_life.h"

#define VERSION		0.359568

/* the arrays and grids. */
int grid_box[GRIDSIZEX][GRIDSIZEY][DNASIZE];
int occp[GRIDSIZEX][GRIDSIZEY];
/* what loop it is. */
int loop=0;

/* the used file pointers. */
FILE *log_file;
FILE *usr_log_file;
FILE *plate;

char p_str[512];
char *plate_name;
unsigned int in_tmp='A';

/* command line changable variables */

int in_menu();
int wait (int sec);

int main(int argc, char *argv[])
{
	WINDOW *borgrid;
	WINDOW *borout;
	
	
	int x=0, y=0;
	int randdir, dir_tmp, m_loop=0, k_loop=0, k_rand, m_rand;
	int dir_x_tmp=0, dir_y_tmp=0;
	
	int loop_tmp=0, loop_runto=9999;
	
	int genlp_f=9999, mutate_f=1, mtf_f=1, help_f=0, spd_f=0;
	int log_f=0, see=0, seed_time=0, st_f=0, mchs_f=25, kill_f=2, kf_f=2, sbs_f=0, fst_f=0, plate_f=0;
	
	int cnt_arg=0;
	int i=0;
	char ch;
	
	/* sets the default paramiters. */
	
	genlp_f=9999; /* # of generations. */
	mutate_f=1; /* # of times a cell is mutated uppon coppying. */
	mtf_f=1; /* # of generations between coppying cycles. */
	mchs_f=25; /* the chanse of a cell being mutated */
	kill_f=2; /* # of generations between killing cycles. */
	kf_f=2; /* how often a cell is killed(the smaller the # the more often). */
	log_f=0;
	spd_f=1;
	see=0;
	sbs_f=1; /* sbs mode on */
	fst_f=1; /* fast in sbs mode on */
	help_f=0;
	seed_time=0;
	plate_f=0;
	st_f=0;
	
	/* processes the shell arguments. */
	if(argc>1){
		for(cnt_arg=1;cnt_arg<=argc;cnt_arg++){
			if(argv[cnt_arg]!=NULL){
				
				/* # of generations. */
				     if(strcmp("-loops",argv[(cnt_arg)])==0){genlp_f=atoi(argv[(cnt_arg+1)])-1;}
				
				/* # of times a cell is mutated uppon coppying. */
				else if(strcmp("-mpc",argv[(cnt_arg)])==0){mutate_f=atoi(argv[(cnt_arg+1)]);}
				
				/* how often a cell is mutated (the smaller the # the more often). */
				else if(strcmp("-chs",argv[(cnt_arg)])==0){mchs_f=atoi(argv[(cnt_arg+1)])-1;}
				
				/* # of generations between coppying cycles. */
				else if(strcmp("-mtc",argv[(cnt_arg)])==0){mtf_f=atoi(argv[(cnt_arg+1)]);}
				
				/* # of generations between killing cycles. */
				else if(strcmp("-klc",argv[(cnt_arg)])==0){kill_f=atoi(argv[(cnt_arg+1)]);}
				
				/* how often a cell is killed (the smaller the # the more often). */
				else if(strcmp("-klf",argv[(cnt_arg)])==0){kf_f=atoi(argv[(cnt_arg+1)])-1;}
				
				/* displaysthe help. */
				else if(strcmp("help",argv[(cnt_arg)])==0){help_f=1;}
				
				/* second by second display by generation. */
				else if(strcmp("-sbs",argv[(cnt_arg)])==0) {
					sbs_f=1;
					if(strcmp("fst",argv[(cnt_arg+1)])==0) {
						fst_f=1;
					}
				}
				
				/* logs statistics. */
				else if(strcmp("-log",argv[(cnt_arg)])==0){log_f=1;}
				
				/* displays statistics. */
				else if(strcmp("-see",argv[(cnt_arg)])==0){see=1;}
				
				/* loading a plate file */
				else if(strcmp("-alp",argv[(cnt_arg)])==0) {
					plate_f=1;
					sbs_f=1;
					/* checks to see if no filename is specified */
					if(argv[(cnt_arg+1)]==NULL){
						printf("PlateFile ERROR. Specifiy a file.\n");
						exit (0);   
					}
					/* allocates space for name in variable, and puts name in variable */
					plate_name=(char *)malloc(strlen(argv[(cnt_arg+1)])+1);
					strcpy(plate_name, argv[(cnt_arg+1)]);
					/* checks to see if plate file exists */
					plate=fopen(plate_name, "r");
					if(!plate){
						printf("PlateFile ERROR. Not a file.\n");
						exit (0);  
					}
					fclose(plate);
				}
				
				/* seed time. */
				else if(strcmp("-st",argv[(cnt_arg)])==0) {
					st_f=1;
					seed_time=atoi(argv[(cnt_arg+1)]);
				}
				
				/* how manny generations to skip bifore updating grid on screen. */
				else if(strcmp("-spd",argv[(cnt_arg)])==0){fst_f=1;spd_f=atoi(argv[(cnt_arg+1)]);}
				
				/*  */
			}
		}
	}
	if(log_f==1) {
		log_file=fopen("log.al.txt", "w");
		if(!log_file){
			printf("LogFile ERROR.\n");
			exit (0); /*return 0;*/   
		}
	}
	/* prints title onto the screen. */
	if(help_f==1){
		printf("===========Array Life==========\n\nShell arguments: \n\n");
		printf("\t-loops\t[# of generations]\n");
		printf("\t-mpc\t[# of mutations per copy]\n");
		printf("\t-chs\t[# chance of mutation per copy]\n");
		printf("\t-mtc\t[# of loops skipped per copy cycle]\n");
		printf("\t-klc\t[# of loops skipped per death cycle]\n");
		printf("\t-klf\t[# chance of surviving per death cycle]\n");
		printf("\t-sbs\tslows down the program to display each generation every second\n");
		printf("\t-alp\t[Template fileame]\n\n");
		printf("===== must have at least one of the folowing:\n\n");
		printf("\t-log\tlogs statistics to file.\n");
		printf("\t-see\tdisplays statistics to screen.\n\n");
		exit (0); /*return 0;*/
	}
	/* seeds the psudorandom number generator. */
	if(st_f==0){seed_time=(unsigned)time(NULL);}
	SRDM(seed_time);
	
	gridsize(GRIDSTUFF);
	
	if(plate_f==0){
		/* clears the grid of left over values. */
		gridsize(GRIDSTUFF);
		/* creates the first cell. */
		create(((GRIDSIZEX-2)/2), ((GRIDSIZEY-2)/2), DNASIZE);
		/*make_wall(2, 1, 1, 20, 5);
        	make_wall(2, 1, 6, 5, 20);
        	make_wall(2, 16, 6, 20, 20);
        	make_wall(2, 6, 16, 15, 20);*/
		
		plate=fopen("latbound.alp", "w");
		if(!plate){
			printf("PlateFile ERROR.\n");
			exit (0);   
		}
		log_plate(plate);
		fclose(plate);
	}
	else {
		gridsize(GRIDSTUFF);
		/* loads plate grid from file */
		plate=fopen(plate_name, "r");
		if(!plate){
			printf("PlateFile ERROR.\n");
			exit (0); /*return 0;*/   
		}
		get_plate(plate);
		fclose(plate);
	}
	/* makes boundery wall, and prevents errors */
	make_wall(HOLLOW, 0, 0, GRIDSIZEX, GRIDSIZEY);
	make_wall(HOLLOW, 0, 0, GRIDSIZEX-1, GRIDSIZEY-1);
	
	if(log_f==1){
		/* prints title into the logfile. */
		fprintf(log_file, "* ******************************* *\n"  );
		fprintf(log_file, "*     --==# Array Life #==--      *\n"  );
		fprintf(log_file, "*         By: TarpeyD12           *\n"  );
		fprintf(log_file, "* =============================== *\n"  );
		fprintf(log_file, "*            log file             *\n"  );
		fprintf(log_file, "* ******************************* *\n\n");
		fprintf(log_file, "\n\noriginal cell:\n");

		/* reopenns the LogFile as append. */
		fclose(log_file);
		log_file=fopen("log.al.txt", "a+");
		if(!log_file){
			printf("LogFile ERROR.\n");
			exit (0); /*return 0;*/   
		}

		/* displays and logs the original cell. */
		log_all_stats(log_file, GRIDSTUFF);
		fprintf(log_file, "\n====================================\n\n");
	}
	/*fclose(log_file);*/
	initscr(); /* ***************************************** start ncurses ***************************************** */
	cbreak();
	/*noecho();*/
	timeout(0);
	keypad(stdscr, TRUE);
	
	if(has_colors()==TRUE && COLORIF==0){
		start_color();
		textcolor(BOLD, WHITE, BLACK);
	}
	
	/* prints the title to the screen. */
	printw("Array Life By: TarpeyD12\n");
	printw("\nStatus of program: v%f.\n", VERSION);
	if(cell_cnt(GRIDSTUFF)>3) {
		printw("\nThere are ");
		textcolor(BOLD, MAGENTA, BLACK);printw("%d", cell_cnt(GRIDSTUFF));
		putstrclr(BOLD, WHITE, BLACK, " cells would you like to see them? (");
		putstrclr(BOLD, GREEN, BLACK, "Y");
		putstrclr(BOLD, WHITE, BLACK, "/");
		putstrclr(BOLD, RED, BLACK, "N");
		putstrclr(BOLD, WHITE, BLACK, ")");
		refresh();
		other_char:
		ch=getchar();
		switch(ch){
			case 'Y':
			case 'y':
				cls(25);
				/*printw("\n\noriginal cells:\n");*/
				all_stats(GRIDSTUFF);
			break;
			
			case 'N':
			case 'n':
				goto no_see_cells;
			break;
			
			default:
				goto other_char;
		}
	}
	else {
		switch(cell_cnt(GRIDSTUFF)){
			case 1:	printw("original cell:\n"); break;
			default: printw("original cells:\n"); break;
		}
		all_stats(GRIDSTUFF);
	}
	no_see_cells:
	printw("\nPress [Return] to initiate the simulation...\n");
	refresh();
	/*WF_ENTER*/
	while(in_tmp!='\n'){in_tmp=getch();}
	
	move(0, 0);
	cls(LINES);
	/*refresh();*/
	/* initalize the used windows. */
	
	grid_scr=create_win(22, 42, 0, 1);
	out_scr=create_win(20, 36, 43, 2);
	borout=create_win(22, 38, 42, 1);
	scrollok(out_scr, TRUE);
	move(0, 0);
	genstats();
	/*printw("\n");*/
	disp_occp_grid(GRIDDISPSTUFF);
	refresh();
	
	/* The Main loop. */
	for(loop=0;loop<=GENLP;/*loop++*/) {
		/* processes the generation(s). */
		/*wmove(out_scr, 0, 0);*/
		loop_tmp=process_gen(spd_f, GENSTUFF);
		loop+=loop_tmp;
		wrefresh(grid_scr);
		wrefresh(out_scr);
		/*wclsb(out_scr, 22, 36);*/
		
		chk_dna(); /* gets rid of 'Cancer' cells. */
		chk_grid(); /* gets rid of error cells */
		/* displays what generation it is. */
		move(0, 0);
		genstats();
		printw("\n");
		disp_occp_grid(GRIDDISPSTUFF);
		wrefresh(grid_scr);
		if(fst_f==0){wait(1);}
		move(LINES-3, 0);
		/* checks to see if there are still cells on the grid. */
		if(cell_cnt(GRIDSTUFF)==0){
			if(sbs_f==0) {
				LEFTME_W
			}
			
			/* displays what generation it is. */
			genstats();
			disp_occp_grid(GRIDDISPSTUFF);
			refresh();
			move(0, 0);
			wprintw(out_scr,"No Living Cells...");
			move(LINES-2, 0);
			printw("\nPress [Return] to exit...");
			refresh();
			wrefresh(out_scr);
			WF_ENTER
			quitme(1); 
		}
		/* In-Simulation commands. */
		move(0, COLS-4);
		printw("[=]");
		refresh();
		in_menu(loop_runto);
	} /* ends the main loop. */
	
	move(0, 0);
	genstats();
	disp_occp_grid(GRIDDISPSTUFF);
	refresh();
	move(LINES-2, 0);
	if(log_f==1){fclose(log_file);}
	if(log_f!=1 && see!=1) {
		wprintw(out_scr,"\nno shell argument(s) set for the results, example: \n%s -log -see", argv[0]);
		wprintw(out_scr,"\nfor more arguments try:\n%s help\n\nexiting...\n", argv[0]);
		wrefresh(out_scr);
	}
	/* the logging */
	if(log_f==1){
		move(LINES-2, 0);
		wprintw(out_scr,"Loging statistics...");
		refresh();
		/*reopens the LogFile*/
		log_file=fopen("log.al.txt", "a+");
		if(!log_file){
			printf("LogFile ERROR.\n");
			refresh();
			exit (0); /*return 0;*/   
		}
		log_genstats(log_file);
		log_occp_grid(log_file);
		log_all_stats(log_file, GRIDSTUFF);
		/*fprintf(log_file, "\n\nstrongest: %d\n\n", strongest());*/
		fclose(log_file);
		wprintw(out_scr,"\tlogged to log.al.txt\n");
		refresh();
	}
	/* printing stats to the screen. */
	if(see==1){
		wprintw(out_scr,"Press [Return] to see individual statistics...\n");
		wrefresh(out_scr);
		WF_ENTER
		cls(25);
		all_stats(GRIDSIZEX, GRIDSIZEY, DNASIZE);
		printw("\n");
		refresh();
	}
	/* waits for user to exit */
	move(LINES-2, 0);
	textcolor(6, 7, 0);
	printw("\nPress [Return] to exit...");
	clsb(3);
	refresh();
	WF_ENTER
	endall:
	endwin();
	quitme(0);
	
	/*exit(0);*/ /* return (0); */
}

int wait(int sec) {
	clock_t wait;
	wait = clock () + sec * CLOCKS_PER_SEC ;
	while (clock() < wait) {}
	return 1;
};

/*
freeing an array

free((cast*)calloc(sizeof(array), sizeof(cast)));

*/
